package in.muton.edushare.panels.assignment;

import in.muton.edushare.components.messaging.api.AssignmentMessage;
import in.muton.edushare.helper.TinyMCEHelper;
import in.muton.edushare.pages.common.EdusharePanel;
import in.muton.edushare.panels.upload.MultipleFileUploadButtonPanel;
import in.muton.edushare.url.URLLoader;
import in.muton.edushare.wicket.models.CayenneModel;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import org.apache.wicket.RestartResponseException;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.markup.html.JavascriptPackageResource;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.form.Button;
import org.apache.wicket.markup.html.form.CheckBox;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.HiddenField;
import org.apache.wicket.markup.html.form.SubmitLink;
import org.apache.wicket.markup.html.form.TextArea;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.link.ExternalLink;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.markup.html.panel.Fragment;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.PropertyModel;

import com.edushare.common.constants.URLConstants;
import com.edushare.common.dao.AssignmentsDAO;
import com.edushare.common.dao.FilesUploadedDAO;
import com.edushare.common.dao.UserAssignmentLinkDAO;
import com.edushare.common.util.DateTimeUtil;
import com.edushare.common.util.URLUtils;
import com.edushare.common.vo.Assignments;
import com.edushare.common.vo.FileDirTypes;
import com.edushare.common.vo.FileDirectories;
import com.edushare.common.vo.FilesUploaded;
import com.edushare.common.vo.Messages;

public class EditAssignmentPanel extends EdusharePanel {

	private static final long serialVersionUID = 3858125534672088095L;
	private final IModel<Assignments> assignmentModel;
	private CheckBox lateSubmission;
	private final CayenneModel<FileDirectories> helpDirModel;
	private final CayenneModel<FileDirectories> solnDirModel;
	
	public EditAssignmentPanel(String id, IModel<Assignments> assignmentModel){
		super(id, assignmentModel);
		this.assignmentModel = assignmentModel;
		this.helpDirModel = new CayenneModel<FileDirectories>(getDir(FileDirTypes.ASSIGNMENT_HELP));
		this.solnDirModel = new CayenneModel<FileDirectories>(getDir(FileDirTypes.ASSIGNMENT_SOLN));
		add(JavascriptPackageResource.getHeaderContribution(CreateAssignment.class, "assnCreate.js"));
		validate();
		loadPanel();
	}

	private FileDirectories getDir(String dirType) {
		if(dirType.equalsIgnoreCase(FileDirTypes.ASSIGNMENT_HELP)){
			System.out.println("DOR: "+new AssignmentsDAO(getORMInterface()).getHelpDirectory(this.assignmentModel.getObject()));
			return new AssignmentsDAO(getORMInterface()).getHelpDirectory(this.assignmentModel.getObject());
		}else if(dirType.equalsIgnoreCase(FileDirTypes.ASSIGNMENT_SOLN)){
			return new AssignmentsDAO(getORMInterface()).getSolutionDirectory(this.assignmentModel.getObject());
		}else{
			throw new IllegalArgumentException("Alllowed file types are: 1. FileDirTypes.ASSIGNMENT_HELP, 2. FileDirTypes.ASSIGNMENT_SOLN");
		}
	}

	private void validate() {
		// TODO Auto-generated method stub
		
	}
	
	private void loadPanel() {
		AssignmentForm f = new AssignmentForm("asnCreateForm");
		f.setOutputMarkupId(true).setMarkupId("asnCreateForm");
		add(f);
		
		assignmentModel.getObject().getPrivacy();
		
		TextField<String> aTitle = 
			new TextField<String>("asnTitle", new PropertyModel<String>(this.assignmentModel, "assignmentTitle"));
		
		aTitle.setOutputMarkupId(true).setMarkupId("asnTitle");
		f.add(aTitle);
		HiddenField<String> startDate = new HiddenField<String>("hAsnStartDate", new PropertyModel<String>(this, "sDate"));
		startDate.setOutputMarkupId(true).setMarkupId("hAsnStartDate");
		HiddenField<String> endDate = new HiddenField<String>("hAsnEndDate", new PropertyModel<String>(this, "eDate"));
		endDate.setOutputMarkupId(true).setMarkupId("hAsnEndDate");
		f.add(startDate);
		f.add(endDate);
		f.add(new UploadFragment("helpUploadBox", helpDirModel));
		f.add(new UploadFragment("solnUploadBox", solnDirModel));
		TextArea<String> aDesc = new TextArea<String>("asnDesc",new PropertyModel<String>(this.assignmentModel, "assignmentDesc"));
		aDesc.add(TinyMCEHelper.getDefaultTinyMCEBehavior());
		f.add(aDesc);
		
		final HiddenField<String> lateDate = new HiddenField<String>("hAsnLateDate", new PropertyModel<String>(this,"lDate"));
		lateDate.setOutputMarkupId(true);
		lateDate.setMarkupId("hAsnLateDate");
		f.add(lateDate);
		lateSubmission = new CheckBox("asnLateCheck", new PropertyModel<Boolean>(this, "lateSubmissionAllowed")){
			@Override
			protected void onModelChanged() {
				System.out.println("== On Model Changed ==");
				try {
					setLDate(lateDate.getInput());
				} catch (ParseException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		};
		lateSubmission.setOutputMarkupId(true).setMarkupId("asnLateCheck");
		f.add(lateSubmission);
		
		f.add(new TextField<String>("maxMarks", new PropertyModel<String>(assignmentModel, "gradingItem.maxMarks")));
		f.add(new TextField<String>("weightage", new PropertyModel<String>(assignmentModel, "gradingItem.weightage")));
		
		final Button asnUpdateButton = new Button("asnUpdateButton"){
			@Override
			public void onSubmit() {
				updateAssignment();
				getORMInterface().commitAllChanges();
				afterUpdated();
			}
		};
		
		//don't show save-as-draft, if the assignment is not draft
		if(this.assignmentModel.getObject().getStatus()!=Assignments.ASSIGNMENT_STATUS_DRAFT)
		{
			asnUpdateButton.setVisible(false);
		}
		f.add(asnUpdateButton);
		
		
		Button asnPublishButton = new Button("asnPublishButton"){
			@Override
			public void onSubmit() {
				if(assignmentModel.getObject().getStatus()!=Assignments.ASSIGNMENT_STATUS_OPEN){
					EditAssignmentPanel.this.assignmentModel.getObject().setStatus(Assignments.ASSIGNMENT_STATUS_OPEN);
					new UserAssignmentLinkDAO(getORMInterface()).linkToAssignees(EditAssignmentPanel.this.assignmentModel.getObject());
					new AssignmentMessage(
							assignmentModel.getObject(), AssignmentMessage.NEW_ASSIGNMENT_CREATED
							).setReciever(assignmentModel.getObject().getCourseInstance())
							 .setPrivacy(Messages.PRIVACY_TYPE_NONE)
							 .send();
				}
				updateAssignment();
				asnUpdateButton.setVisible(false);
				getORMInterface().commitAllChanges();
				afterPublished();
			}
		};
		f.add(asnPublishButton);
		
		Button asnDelButton = new Button("asnDelButton"){
			@Override
			public void onSubmit() {
				deleteAssigment();
				
				getORMInterface().commitAllChanges();
				afterDeleted();
			}
		};
		f.add(asnDelButton);
		
		Button asnCancelButton = new Button("asnCancelButton"){
			@Override
			public void onSubmit() {
				afterCanceled();
			}
		};
		asnCancelButton.setDefaultFormProcessing(false);
		f.add(asnCancelButton);
	}
	
	public class AssignmentForm extends Form<Void>{

		private static final long serialVersionUID = 5187249804526260047L;

		public AssignmentForm(String id) {
				super(id);								
		}
	}
	
	public Boolean getLateSubmissionAllowed(){
		if(this.assignmentModel.getObject().getAllowLate()!=null && 
				this.assignmentModel.getObject().getAllowLate() == Assignments.ASSIGNMENT_ALLOW_LATE_SUBMIT){
			return new Boolean(true);
		}else{
			return new Boolean(false);
		}
	}
	
	public void setLateSubmissionAllowed(Boolean isLateSubmitAllowed){
		if(isLateSubmitAllowed){
			this.assignmentModel.getObject().setAllowLate(Assignments.ASSIGNMENT_ALLOW_LATE_SUBMIT);
		}else{
			this.assignmentModel.getObject().setAllowLate(Assignments.ASSIGNMENT_NO_LATE_SUBMIT);
		}
	}
	
	private void updateAssignment() {
		//the model is updated... we can perform validations... not now.
		getORMInterface().commitAllChanges();
	}

	private void deleteAssigment() {
		if(this.assignmentModel!=null && this.assignmentModel.getObject()!=null){
			new AssignmentMessage(assignmentModel.getObject(),
					AssignmentMessage.ASSIGNMENT_CANCELLED).setReciever(
					assignmentModel.getObject().getCourseInstance()).setPrivacy(
					Messages.PRIVACY_TYPE_NONE).send();
			new AssignmentsDAO(getORMInterface()).deleteAssignmentsCompletly(this.assignmentModel.getObject());
		}
		
	}
	
	/** date setter getter */
	public String getSDate(){
		return getFormattedDate(this.assignmentModel.getObject().getStartDate());
	}
	
	public void setSDate(String date) throws ParseException{
		this.assignmentModel.getObject().setStartDate(getDateFromStr(date));
	}
	
	public String getEDate(){
		return getFormattedDate(this.assignmentModel.getObject().getEndDate());
	}
	
	public void setEDate(String date) throws ParseException{
		this.assignmentModel.getObject().setEndDate(DateTimeUtil.getEOTD(getDateFromStr(date)));
	}
	
	public String getLDate(){
		return getFormattedDate(this.assignmentModel.getObject().getLateSubmDate());
	}
	
	public void setLDate(String date) throws ParseException{
		System.out.println("this.lateSubmission.getModelObject()="+this.lateSubmission.getModelObject());
		if(this.lateSubmission.getModelObject()){
			this.assignmentModel.getObject().setLateSubmDate(DateTimeUtil.getEOTD(getDateFromStr(date)));
		}
		else{
			this.assignmentModel.getObject().setLateSubmDate(null);
		}
	}

	private Date getDateFromStr(String date) throws ParseException {
		return new SimpleDateFormat("dd MMM yyyy").parse(date);
	}
	
	private String getFormattedDate(Date date) {
		if(date!=null){
			return new SimpleDateFormat("dd MMM yyyy").format(date);
		}
		else{
			return null;
		}
	}

	/** Upload Fragment */
	public class UploadFragment extends Fragment{

		public IModel<FileDirectories> uploadDirModel;
		
		public UploadFragment(String id, IModel<FileDirectories> fileDirModel) {
			super(id, "uploadFragment", EditAssignmentPanel.this);
			
			this.uploadDirModel = fileDirModel;
			final WebMarkupContainer helpFileList = new WebMarkupContainer("helpFileList");
			helpFileList.setOutputMarkupId(true);
			add(helpFileList);
			ListView<FilesUploaded> hfileList = 
				new ListView<FilesUploaded>("helpFileHolder", new PropertyModel<List<FilesUploaded>>(this.uploadDirModel, "filesUploaded")) 
			{

				@Override
				protected void populateItem(ListItem<FilesUploaded> item) {
					final CayenneModel<FilesUploaded> uf = new CayenneModel<FilesUploaded>(item.getModel().getObject());
					item.add(new ExternalLink("helpFileUrl", URLUtils.getUrlFromRelativePath(uf.getObject().getFileRelativePath()), uf.getObject().getFileOrigName()));
					item.add(new SubmitLink("delFile"){

						private static final long serialVersionUID = -8146045310037750943L;
						@Override
						public void onSubmit() {
							new FilesUploadedDAO(getORMInterface()).deleteFileUploaded(uf.getObject());
							getORMInterface().commitAllChanges();
						}
					}.setDefaultFormProcessing(false));
				}
			};
			
			helpFileList.add(hfileList);
			//f.add(new MultiUpload("uloadPanel", tempHelpDirId));
			add(new MultipleFileUploadButtonPanel("uloadPanel",fileDirModel) {

				@Override
				public void onUploadWindowClose(AjaxRequestTarget target) {
					target.addComponent(helpFileList);
				}

			});
			
		}
		
		/*public List<FilesUploaded> getFilesInDir(){
			FileDirectories fd = new FileDirectoriesDAO(getORMInterface()).getTempDirectory(this.uploadDirTempIdModel.getObject());
			if(fd!=null){
				return fd.getFilesUploaded();
			}else
			{
				return null;
			}
		}*/
		
	}
	
	/** Override methods */
	
	/** Override this method to set after assignment Updated */
	public void afterUpdated(){};
	/** Override this method to do something after Deleted */
	public void afterDeleted(){
		throw new RestartResponseException(URLLoader.getPageClass(URLConstants.LOGIN_PATH));
	};
	/** Override this method to do something after Canceled */
	public void afterCanceled(){
		throw new RestartResponseException(URLLoader.getPageClass(URLConstants.LOGIN_PATH));
	}
	/** Override this method to do something after Published */
	public void afterPublished(){}
}
